# !/usr/bin/env python
# -*- coding: utf-8 -*-
"""
 -------------------------------------------------
    File Name:     collect_hooks.py
    Description:   文件收集相关钩子🪝
 -------------------------------------------------
 """

import pytest
import yaml
from pathlib import Path
from typing import Generator


def pytest_collect_file(parent: pytest.Collector, path: Path) -> pytest.File | None:
    """
    pytest 的文件收集钩子函数。
    用于在 pytest 的收集阶段判断如何处理目录中的文件。

    :param parent: pytest 的父节点（通常是目录节点）。
    :param path: 当前文件路径（类型为 pathlib.Path）。

    :return: 如果是 .yaml 文件，返回自定义的 YamlFile 收集器；否则返回 None。
    """
    if path.suffix == ".yaml":  # 使用 pathlib.Path 的 suffix 检查文件扩展名
        print(f"Collecting YAML file: {path.name}")
        return YamlFile.from_parent(parent, path=path)


class YamlFile(pytest.File):
    """
    自定义 YAML 文件收集器，用于解析 YAML 文件并生成测试用例项。
    """

    def collect(self) -> Generator[pytest.Item, None, None]:
        """
        解析 YAML 文件并生成测试用例项。

        :return: 生成器对象，每个对象表示一个测试用例（YamlItem）。
        """
        try:
            with self.path.open() as f:
                data = yaml.safe_load(f)  # 使用 PyYAML 加载 YAML 文件内容
        except yaml.YAMLError as e:
            raise pytest.UsageError(f"Failed to parse YAML file {self.path}: {e}")

        filename = self.path.stem  # 获取文件名（不包括扩展名）

        # 遍历 YAML 文件中的 "test_cases" 列表
        for case in data.get("test_cases", []):
            case_name = case.get("name")
            if not case_name:
                raise pytest.UsageError(f"Test case in {self.path} is missing a 'name' field.")

            # 使用文件名和用例名称组合成唯一的测试项名称
            full_case_name = f"{filename}::{case_name}"
            yield YamlItem.from_parent(self, name=full_case_name, case_data=case)


class YamlItem(pytest.Item):
    """
    自定义测试用例项，用于表示 YAML 文件中的单个测试用例。
    """

    def __init__(self, parent: pytest.Collector, name: str, case_data: dict):
        """
        初始化 YamlItem 实例。

        :param name: 测试用例名称。
        :param parent: 所属的 YAML 文件（YamlFile）。
        :param case_data: 测试用例的具体数据。
        """
        super().__init__(name, parent)  # 调用 pytest.Item 的构造方法
        self.case_data = case_data  # 保存测试用例数据

    def runtest(self):
        """
        执行测试用例的逻辑。
        这里模拟发送 HTTP 请求，并根据期望的状态码进行断言。
        """
        print(f"Running test: {self.name}")
